package game.coord;

import game.util.Logger;

import java.util.ArrayList;
import java.util.List;


public class MooreCellWithChildren extends MooreCell
{
    private int                   position    = 0;
    
    public static final int       TOPLEFT     = 1;
    public static final int       TOP         = 2;
    public static final int       TOPRIGHT    = 3;
    public static final int       LEFT        = 4;
    public static final int       CENTER      = 5;
    public static final int       RIGHT       = 6;
    public static final int       BOTTOMLEFT  = 7;
    public static final int       BOTTOM      = 8;
    public static final int       BOTTOMRIGHT = 9;
    
    // dad
    private MooreCellWithChildren parent;
    // children
    private MooreCellWithChildren topLeftChild;
    private MooreCellWithChildren topChild;
    private MooreCellWithChildren topRightChild;
    private MooreCellWithChildren leftChild;
    private MooreCellWithChildren centerChild;
    private MooreCellWithChildren rightChild;
    private MooreCellWithChildren bottomLeftChild;
    private MooreCellWithChildren bottomChild;
    private MooreCellWithChildren bottomRightChild;
    
    public MooreCellWithChildren(MooreCellWithChildren parent, int position)
    {
        if (parent == null)
        {
            Logger.trace("PARENT-SETNULL: ", getPathString());
        }
        this.parent = parent;
        this.position = position;
    }
    
    public int getGeneration()
    {
        int generation = 1;
        MooreCellWithChildren parent = getParent();
        while (parent != null)
        {
            generation++;
            parent = parent.getParent();
        }
        return generation;
    }
    
    public int getPosition()
    {
        return position;
    }
    
    public int getPosition(MooreCellWithChildren neighbor)
    {
        if (neighbor != null)
        {
            if (neighbor.equals(getTopLeft()))
            {
                return TOPLEFT;
            }
            if (neighbor.equals(getTop()))
            {
                return TOP;
            }
            if (neighbor.equals(getTopRight()))
            {
                return TOPRIGHT;
            }
            if (neighbor.equals(getLeft()))
            {
                return LEFT;
            }
            if (neighbor.equals(this))
            {
                return CENTER;
            }
            if (neighbor.equals(getRight()))
            {
                return RIGHT;
            }
            if (neighbor.equals(getBottomLeft()))
            {
                return BOTTOMLEFT;
            }
            if (neighbor.equals(getBottom()))
            {
                return BOTTOM;
            }
            if (neighbor.equals(getBottomRight()))
            {
                return BOTTOMRIGHT;
            }
        }
        return 0;
    }
    public int getChildPosition(MooreCellWithChildren child)
    {
        if (child != null)
        {
            if (child.equals(getTopLeftChild()))
            {
                return TOPLEFT;
            }
            if (child.equals(getTopChild()))
            {
                return TOP;
            }
            if (child.equals(getTopRightChild()))
            {
                return TOPRIGHT;
            }
            if (child.equals(getLeftChild()))
            {
                return LEFT;
            }
            if (child.equals(getCenterChild()))
            {
                return CENTER;
            }
            if (child.equals(getRightChild()))
            {
                return RIGHT;
            }
            if (child.equals(getBottomLeftChild()))
            {
                return BOTTOMLEFT;
            }
            if (child.equals(getBottomChild()))
            {
                return BOTTOM;
            }
            if (child.equals(getBottomRightChild()))
            {
                return BOTTOMRIGHT;
            }
        }
        return 0;
    }
    
    public long getPath()
    {
        long path = 0;
        MooreCellWithChildren cell = this;
        int exponent = 1;
        do
        {
            int position = cell.getPosition();
            path += position * exponent;
            // next exponent
            exponent *= 10;
            cell = cell.getParent();
        }
        while (cell != null);
        return path;
    }
    
    public List<Integer> getPathArray()
    {
        List<Integer> list = new ArrayList<>();
        MooreCellWithChildren parent = getParent();
        if (parent != null)
        {
            list.addAll(parent.getPathArray());
        }
        list.add(getPosition());
        return list;
    }
    
    public String getPathString()
    {
        StringBuilder path = new StringBuilder();
        for (Integer p : getPathArray())
        {
            path.append(p);
        }
        return path.substring(0, path.length() - 1);
    }
    
    public MooreCellWithChildren getParent()
    {
        return parent;
    }
    
    public MooreCellWithChildren getChild(int position)
    {
        MooreCellWithChildren child = null;
        switch (position)
        {
            case TOPLEFT:
                child = getTopLeftChild();
                break;
            case TOP:
                child = getTopChild();
                break;
            case TOPRIGHT:
                child = getTopRightChild();
                break;
            case LEFT:
                child = getLeftChild();
                break;
            case CENTER:
                child = getCenterChild();
                break;
            case RIGHT:
                child = getRightChild();
                break;
            case BOTTOMLEFT:
                child = getBottomLeftChild();
                break;
            case BOTTOM:
                child = getBottomChild();
                break;
            case BOTTOMRIGHT:
                child = getBottomRightChild();
                break;
        }
        return child;
    }
    public void setChild(MooreCellWithChildren child)
    {
        if (child == null)
        {
            Logger.trace("CHILD-SETNULL: ", getPathString());
        }
        switch (child.getPosition())
        {
            case TOPLEFT:
                setTopLeftChild(child);
                break;
            case TOP:
                setTopChild(child);
                break;
            case TOPRIGHT:
                setTopRightChild(child);
                break;
            case LEFT:
                setLeftChild(child);
                break;
            case CENTER:
                setCenterChild(child);
                break;
            case RIGHT:
                setRightChild(child);
                break;
            case BOTTOMLEFT:
                setBottomLeftChild(child);
                break;
            case BOTTOM:
                setBottomChild(child);
                break;
            case BOTTOMRIGHT:
                setBottomRightChild(child);
                break;
        }
        child.position = position;
    }
    
    private MooreCellWithChildren getTopLeftChild()
    {
        return topLeftChild;
    }

    private void setTopLeftChild(MooreCellWithChildren topLeftChild)
    {
        this.topLeftChild = topLeftChild;
    }

    private MooreCellWithChildren getTopChild()
    {
        return topChild;
    }

    private void setTopChild(MooreCellWithChildren topChild)
    {
        this.topChild = topChild;
    }

    private MooreCellWithChildren getTopRightChild()
    {
        return topRightChild;
    }

    private void setTopRightChild(MooreCellWithChildren topRightChild)
    {
        this.topRightChild = topRightChild;
    }

    private MooreCellWithChildren getLeftChild()
    {
        return leftChild;
    }

    private void setLeftChild(MooreCellWithChildren leftChild)
    {
        this.leftChild = leftChild;
    }

    private MooreCellWithChildren getCenterChild()
    {
        return centerChild;
    }

    private void setCenterChild(MooreCellWithChildren centerChild)
    {
        this.centerChild = centerChild;
    }

    private MooreCellWithChildren getRightChild()
    {
        return rightChild;
    }

    private void setRightChild(MooreCellWithChildren rightChild)
    {
        this.rightChild = rightChild;
    }

    private MooreCellWithChildren getBottomLeftChild()
    {
        return bottomLeftChild;
    }

    private void setBottomLeftChild(MooreCellWithChildren bottomLeftChild)
    {
        this.bottomLeftChild = bottomLeftChild;
    }

    private MooreCellWithChildren getBottomChild()
    {
        return bottomChild;
    }

    private void setBottomChild(MooreCellWithChildren bottomChild)
    {
        this.bottomChild = bottomChild;
    }

    private MooreCellWithChildren getBottomRightChild()
    {
        return bottomRightChild;
    }
    
    private void setBottomRightChild(MooreCellWithChildren bottomRightChild)
    {
        this.bottomRightChild = bottomRightChild;
    }
    
    @Override
    public MooreCellWithChildren getTopLeft()
    {
        MooreCellWithChildren topLeft = (MooreCellWithChildren) super.getTopLeft();
        return topLeft;
    }
    
    @Override
    public MooreCellWithChildren getTop()
    {
        MooreCellWithChildren top = (MooreCellWithChildren) super.getTop();
        return top;
    }
    
    @Override
    public MooreCellWithChildren getTopRight()
    {
        MooreCellWithChildren topRight = (MooreCellWithChildren) super.getTopRight();
        return topRight;
    }
    
    @Override
    public MooreCellWithChildren getLeft()
    {
        MooreCellWithChildren left = (MooreCellWithChildren) super.getLeft();
        return left;
    }
    @Override
    public MooreCellWithChildren getRight()
    {
        MooreCellWithChildren right = (MooreCellWithChildren) super.getRight();
        return right;
    }
    
    @Override
    public MooreCellWithChildren getBottomLeft()
    {
        MooreCellWithChildren bottomLeft = (MooreCellWithChildren) super.getBottomLeft();
        return bottomLeft;
    }
    
    @Override
    public MooreCellWithChildren getBottom()
    {
        MooreCellWithChildren bottom = (MooreCellWithChildren) super.getBottom();
        return bottom;
    }
    
    @Override
    public MooreCellWithChildren getBottomRight()
    {
        MooreCellWithChildren bottomRight = (MooreCellWithChildren) super.getBottomRight();
        return bottomRight;
    }

    public int getChildGenerations()
    {
        int c = 0;
        MooreCellWithChildren centerChild = getCenterChild();
        while (centerChild != null)
        {
            centerChild = centerChild.getCenterChild();
            c++;
        }
        return c;
    }
    
    public static int countChilds(int generations)
    {
        int childs = 1;
        // every generation has 9 children
        for (int i = 0; i < generations; i++)
        {
            childs *= 9;
        }
        return childs;
    }
}
